/*
 * Copyright (C) 2023, KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

#include "shortcuts-window.h"
#include "global-settings.h"
#include "shortcut-model-manager.h"
#include "hand-gesture-helper.h"
#include "window-blur-helper.h"
#include "event-track.h"

#include <QScreen>
#include <QQuickItem>
#include <QQuickWindow>
#include <QResizeEvent>
#include <QRect>
#include <QVariant>
#include <QEvent>
#include <QGuiApplication>
#include <QX11Info>
#include <KWindowEffects>
#include <KWindowSystem>
#include <QPushButton>
#include <QQmlContext>
#include <QRegion>

ShortcutsWindow::ShortcutsWindow(QWindow *parent) : SharedEngineView(parent)
{
    setResizeMode(UkuiQuick::SharedEngineView::SizeViewToRootObject);
    // 去除标题栏等
    //setFlags(flags() | Qt::FramelessWindowHint);
    m_windowProxy = new UkuiQuick::WindowProxy2(this);
    onPrimaryScreenChanged(QGuiApplication::primaryScreen());
    m_isTabletMode = Sidebar::GlobalSettings::globalInstance()->getValue(TABLET_MODE).toBool();

    // 加载数据
    initUI();
    // 信号
    initConnections();

    // 测试切换功能
    //QPushButton *button = new QPushButton("hahahah");
    //connect(button, &QPushButton::clicked, this, [this] {
    //    onTabletModeChanged();
    //});
    //button->resize(200, 100);
    //button->show();
    //KWindowSystem::setType(button->winId(), NET::ScreenLock);
}

void ShortcutsWindow::initUI()
{
    setColor(Qt::transparent);

    m_windowProxy->setWindowType(UkuiQuick::WindowType::SystemWindow);
    setBlurStrength();

    // 上下文属性
    auto modelManager = new UkuiShortcut::ShortcutModelManager(this);
    rootContext()->setContextProperty("modelManager", modelManager);
    rootContext()->setContextProperty("mainWindow", this);

    // 加载ui
    engine()->addImportPath("qrc:///qml");
    setSource(QUrl("qrc:///qml/Shortcuts.qml"));

    updateEffects();

    connect(modelManager, &UkuiShortcut::ShortcutModelManager::requestExecAction, this, [this] (UkuiShortcut::PluginMetaType::PredefinedAction action) {
        switch (action) {
            default:
            case UkuiShortcut::PluginMetaType::NoAction:
                break;
            case UkuiShortcut::PluginMetaType::Hide:
                hide();
                break;
        }
    });
}

void ShortcutsWindow::initConnections()
{
    // 信号
    connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &ShortcutsWindow::onPrimaryScreenChanged);
    connect(Sidebar::GlobalSettings::globalInstance(), &Sidebar::GlobalSettings::valueChanged, this, [this] (const QString &key) {
        if (key == UKUI_PANEL_POSITION_KEY) {
            updateGeometry();
        } else if (key == TABLET_MODE) {
            onTabletModeChanged();
        }
    });

    // 失焦退出
    connect(this, &QQuickWindow::activeFocusItemChanged, this, [this] {
        if (!activeFocusItem()) {
            activeShortcutsWindow(false);
        }
    });
}

void ShortcutsWindow::resizeEvent(QResizeEvent *event)
{
    SharedEngineView::resizeEvent(event);
    updateGeometry();
}

void ShortcutsWindow::updateGeometry()
{
    if (!screen()) {
        return;
    }

    QRect newGeometry;
    if (m_isTabletMode) {
        newGeometry = screen()->geometry();
    } else {
        int pos = Sidebar::GlobalSettings::globalInstance()->getValue(UKUI_PANEL_POSITION_KEY).toInt();
        int panelSize = Sidebar::GlobalSettings::globalInstance()->getValue(UKUI_PANEL_SIZE_KEY).toInt();
        int margin = windowMargin();
        //QRect rect = screen()->availableGeometry();
        QRect rect = screen()->geometry();
        QPoint point;
        // 上: 1, 下: 0, 左: 2, 右: 3
        switch (pos) {
            default:
            case 0:
                point.setX(rect.right() - width() - margin);
                point.setY(rect.bottom() - height() - margin - panelSize);
                //KWindowEffects::slideWindow(this, KWindowEffects::BottomEdge);
                break;
            case 1:
                point.setX(rect.right() - width() - margin);
                point.setY(rect.top() + margin + panelSize);
                //KWindowEffects::slideWindow(this, KWindowEffects::TopEdge);
                break;
            case 2:
                point.setX(rect.left() + margin + panelSize);
                point.setY(rect.bottom() - height() - margin);
                //KWindowEffects::slideWindow(this, KWindowEffects::LeftEdge);
                break;
            case 3:
                point.setX(rect.right() - width() - margin - panelSize);
                point.setY(rect.bottom() - height() - margin);
                //KWindowEffects::slideWindow(this, KWindowEffects::RightEdge);
                break;
        }

        QRect geometry(point, ShortcutsWindow::size());
        if (rootObject()) {
            geometry.setSize(rootObject()->size().toSize());
        }

        newGeometry = geometry;
    }

    setGeometry(newGeometry);
    m_windowProxy->setPosition(newGeometry.topLeft());
}

bool ShortcutsWindow::event(QEvent *event)
{
    switch (event->type()) {
        case QEvent::Show:
            if (QX11Info::isPlatformX11()) {
                requestActivate();
            }
            break;
        default:
            break;
    }
    return SharedEngineView::event(event);
}

bool ShortcutsWindow::isTabletMode() const
{
    return m_isTabletMode;
}

int ShortcutsWindow::windowMargin() const
{
    return 8;
}

void ShortcutsWindow::onPrimaryScreenChanged(QScreen *screen)
{
    if (ShortcutsWindow::screen()) {
        ShortcutsWindow::screen()->disconnect(this);
    }

    setScreen(screen);
    if (screen) {
        connect(screen, &QScreen::geometryChanged, this, &ShortcutsWindow::updateGeometry);
    }

    updateGeometry();
}

void ShortcutsWindow::onTabletModeChanged()
{
    //bool toTabletMode = !m_isTabletMode;
    bool toTabletMode = Sidebar::GlobalSettings::globalInstance()->getValue(TABLET_MODE).toBool();
    if (toTabletMode) {
        activeShortcutsWindow(false);
    } else {
        hide();
    }

    m_isTabletMode = toTabletMode;
    updateEffects();

    Q_EMIT tabletModeChanged();
}

void ShortcutsWindow::updateEffects()
{
    setResizeMode(m_isTabletMode ? SizeRootObjectToView : SizeViewToRootObject);
    updateGeometry();

    Sidebar::HandGestureHelper::getInstance()->disconnect(this);
    if (m_isTabletMode) {
        //KWindowEffects::slideWindow(this, KWindowEffects::NoEdge);
        connect(Sidebar::HandGestureHelper::getInstance(),&Sidebar::HandGestureHelper::controlCenterCalled,
                this, &ShortcutsWindow::moveShortcutPanel);
        connect(Sidebar::HandGestureHelper::getInstance(), &Sidebar::HandGestureHelper::right2LeftReleased,
                this, &ShortcutsWindow::onRight2LeftReleased);
    } else {
        setBlurStrength();
    }
}

void ShortcutsWindow::moveShortcutPanel(int posX)
{
    if (!rootObject()) {
        return;
    }

    if (!isVisible()) {
        QMetaObject::invokeMethod(rootObject(), "initTabletProp", Qt::DirectConnection);
        show();
    }

    int dx = geometry().right() - posX;
    QMetaObject::invokeMethod(rootObject(), "moveShortcutPanel", Qt::DirectConnection, Q_ARG(QVariant, (dx < 0 ? 0 : dx)));
}

void ShortcutsWindow::onRight2LeftReleased(int posX, int posY)
{
    Q_UNUSED(posY)
    if (rootObject()) {
        int dx = geometry().right() - posX;
        bool active = (dx >= geometry().width() * 0.05);
        QMetaObject::invokeMethod(rootObject(), "activePanelOnTablet", Qt::DirectConnection, Q_ARG(QVariant, active));

        if (active) {
            QVariantMap map;
            map.insert("type", "slide");
            Sidebar::EventTrack::instance()->sendSlideEvent("open_sidebar", "sidebar", map);
        }
    }
}

void ShortcutsWindow::setBlurStrength(quint32 strength)
{
    KWindowEffects::enableBlurBehindWithStrength(this, true, QRegion(), strength);
}

void ShortcutsWindow::activeShortcutsWindow(bool active)
{
    if (!rootObject()) {
        hide();
        return;
    }

    if (active == isVisible()) {
        return;
    }

    if (m_isTabletMode) {
        if (active) {
            QMetaObject::invokeMethod(rootObject(), "initTabletProp", Qt::DirectConnection);
            show();
        }
        QMetaObject::invokeMethod(rootObject(), "activePanelOnTablet", Qt::DirectConnection, Q_ARG(QVariant, active));

    } else {
        for (const auto& screen : QGuiApplication::screens()) {
            if (screen->geometry().contains(QCursor::pos())) {
                this->setScreen(screen);
                break;
            }
        }
        setVisible(active);
    }
}
